-
Notifications
You must be signed in to change notification settings - Fork 43
feat: Add pnpm monorepo support for Metro bundler #160
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
## 주요 변경사항 ### 1. enhancedResolver.ts - React/React Native 버전 충돌 해결 - enhanced-resolve의 alias 기능을 추가하여 react-native와 react를 로컬 node_modules로 강제 - pnpm 모노레포에서 여러 React Native 버전이 공존할 때 발생하는 버전 충돌 문제 해결 - 각 앱이 자신의 package.json에 명시된 정확한 버전을 사용하도록 보장 ### 2. DependencyGraph.js - pnpm symlink SHA-1 계산 지원 - pnpm의 .pnpm 가상 디렉토리 구조에서 발생하는 SHA-1 계산 실패 문제 해결 - 2단계 fallback 로직 추가: 1. resolvedPath로 SHA-1 조회 실패 시 원본 filename으로 재시도 2. 여전히 실패 시 파일 내용을 직접 읽어 SHA-1 계산 - Metro의 HasteFS가 pnpm symlink를 올바르게 처리할 수 있도록 개선 ### 3. getMetroConfig.ts - 모노레포 모듈 해상도 최적화 - disableHierarchicalLookup 기본값을 true로 설정하여 상위 디렉토리 탐색 방지 - monorepo root를 watchFolders에서 제거하여 불필요한 파일 감시 감소 - 각 앱이 독립적으로 의존성을 해상하도록 개선 ## 해결된 문제 1. **SHA-1 계산 실패**: pnpm symlink로 인한 "SHA-1 is not computed" 에러 해결 2. **React Native 버전 충돌**: 모노레포 내 서로 다른 RN 버전 사용 시 발생하는 SyntaxError 해결 3. **Peer dependency 해상도**: 로컬 node_modules의 올바른 peer dependency 해상 보장 ## 테스트 환경 - pnpm workspace 모노레포 - apps/expo: React Native 0.81.5 - apps/toss: React Native 0.72.6 - @granite-js/mpack: 0.1.31 ## 관련 이슈 이 변경사항은 pnpm 모노레포 환경에서 Granite 프레임워크를 사용할 때 발생하는 모듈 해상도 및 번들링 문제를 근본적으로 해결합니다.
|
Someone is attempting to deploy a commit to the Toss Team on Vercel. A member of the Team first needs to authorize it. |
|
Additional Configuration for pnpm Monorepo UsersOptional: Project-level Metro Configuration OverrideWhile the changes in this PR make Granite work seamlessly with pnpm monorepos, users may want additional control at the project level. Here's an example File: const path = require('path');
const { getMetroConfig } = require('@granite-js/mpack/dist/metro/getMetroConfig');
module.exports = (async () => {
const config = await getMetroConfig(
{ rootPath: __dirname },
{
resolver: {
// Force Metro to use the local react-native installation
extraNodeModules: {
'react-native': path.join(__dirname, 'node_modules', 'react-native'),
},
// Optional: Block specific versions if needed (e.g., wrong version from sibling apps)
blockList: [/react-native@0\.81\.5/],
},
}
);
return config;
})();When to Use This ConfigurationYou typically DON'T need this if:
You MAY want this if:
Configuration Explanation1.
2.
NoteWith the fixes in this PR (especially the Real-world ExampleIn our testing monorepo with 2 apps:
App B's metro.config.js: blockList: [/react-native@0\.81\.5/] // Explicitly blocks App A's versionThis ensures App B never accidentally picks up App A's React Native version during Metro's module resolution. |
Summary
This PR adds support for pnpm workspace monorepos in Granite's Metro bundler configuration, resolving critical issues with module resolution and bundling in pnpm-based projects.
Problem Statement
When using Granite in a pnpm workspace monorepo with multiple apps using different React Native versions, the following issues occur:
.pnpmvirtual directory due to symlink handlingExample Error Scenario
Monorepo Structure:
Errors encountered:
Changes Made
1. Enhanced Module Resolver (
enhancedResolver.ts)Added
aliasconfiguration to force local React/React Native versions:Why this works:
reactandreact-nativefrom each app's localnode_modulesmodules: ['node_modules', ...]2. Dependency Graph SHA-1 Fallback (
DependencyGraph.js)Added 2-tier fallback logic for SHA-1 computation:
Why this works:
3. Metro Configuration Optimization (
getMetroConfig.ts)Changes:
disableHierarchicalLookup: trueas defaultwatchFoldersWhy this works:
Testing
Environment:
Test Results:
Patch File for Users
For users who want to apply this fix immediately without waiting for a release, here's a pnpm patch:
1. Create patch:
2. Apply changes from this PR to the temporary directory
3. Commit patch:
4. The patch will be saved to
patches/@[email protected]and automatically added topackage.json:{ "pnpm": { "patchedDependencies": { "@granite-js/[email protected]": "patches/@[email protected]" } } }Breaking Changes
None. These changes are backward compatible:
disableHierarchicalLookupcan still be overridden in configBenefits
Related Issues
This PR addresses the fundamental incompatibility between Granite's Metro bundler and pnpm workspace monorepos, particularly when multiple React Native versions coexist.
Tested with: